home *** CD-ROM | disk | FTP | other *** search
- #include <time.h>
- #include <malloc.h>
- #include <stdlib.h>
- #include <mem.h>
- #include <wgt5.h>
-
- /*
- m
- ╔═════════════════════════════════════════════════════════════════╗
- ║ █▓▒░ WordUp Graphics Toolkit V5.0 ░▒▓█ ║
- ║ Source Code Copyright 1995 Egerter Software ║
- ╟─────────────────────────────────────────────────────────────────╢
- ║ Module: wgtscrol.c ║
- ║ Contains: A full scrolling game engine. ║
- ║ wloadmap, wsavemap, soverlap, wscrollwindow, ║
- ║ wshowwindow, winitscroll, ║
- ║ wgetworldblock, wputworldblock, wshowobjects, ║
- ║ wfreemap, wendscroll, wcopyscroll, ║
- ║ wgetworldpixel, is_in_window, wscreen_coordx, ║
- ║ wscreen_coordy, wcopymap ║
- ║ ║
- ║ Last Revised: April 25, 1995 ║
- ║ ║
- ║ Written by: Chris Egerter WATCOM PROTECTED MODE! ║
- ╚═════════════════════════════════════════════════════════════════╝
- */
-
- static struct {
- char patch_id[8];
- char fname[12];
- float version;
- } patch_struct = {"WGTPATCH", "wgtscrol", 1.0} ;
-
- #pragma aux putxray "_*" parm caller [edi] [esi] [ebx] modify exact [eax ebx ecx esi edi];
- extern void putxray (void *dst, void *src, int len);
-
- int transparenttile;
-
-
- short skippedframe = 0, noscrollupdate = 0;
-
- #define NORMAL 0
- #define PARALLAX 1
- #define MAXWINDOWS 50
-
- /* users should know about these */
- block *scrolltiles[MAXWINDOWS];
- wgtmap scrollmaps[MAXWINDOWS];
-
- wgtmap scrollblock[MAXWINDOWS];
- /* Holds the image for the scrolling window */
-
- short mapwidth[MAXWINDOWS], mapheight[MAXWINDOWS];
- /* the width and height (in tiles) of the current map loaded */
-
- short tilewidth[MAXWINDOWS], tileheight[MAXWINDOWS];
- /* the width and height (in pixels) of tiles */
-
- typedef struct { /* object structure */
- char on; /* sprite is turned on=1 */
- short x; /* world x coordinate */
- short y; /* world y coordinate */
- unsigned short num; /* sprite # from sprites array to show */
- } scrollsprite;
-
- short wgtparallax;
-
- short windowminx[MAXWINDOWS], windowminy[MAXWINDOWS],
- windowmaxx[MAXWINDOWS], windowmaxy[MAXWINDOWS];
- /* coords of scrolling area */
-
- short worldx[MAXWINDOWS];
- short worldy[MAXWINDOWS]; /* world coordinates of top left corner of
- scrolling window */
-
- short worldmaxx[MAXWINDOWS], worldmaxy[MAXWINDOWS];
- /* world max x and y for window. These are calculated so you can't scroll
- past the end of the world, depends on window size */
-
- short windowwidth[MAXWINDOWS], windowheight[MAXWINDOWS];
- /* Size of window (in tiles) */
-
- /* A copyright statement to store in executables */
- char *copyrscroll="WordUp Graphics Toolkit:Multidirectional Scrolling Library Copyright 1995 Egerter Software";
-
-
- /* externals */
- extern short tx,ty,bx,by; /* clipping vars */
- /* top x, top y, bottom x, bottom y */
-
-
- /* funcs */
- void winitscroll (short currentwindow, short mode, short link, short xwidth,
- short ywidth, block *tileref);
- /* defines window size, and sets up vars */
-
- void wshowwindow (short currentwindow, short posx, short posy);
- /* draw the tiles on at a beginning place and sets up more vars */
-
- void wscrollwindow (short currentwindow, short wspeedx, short wspeedy);
- /* scroll the screen */
-
- void wshowobjects (short currentwindow, short start, short end,
- block *sprites, scrollsprite *wobjects);
- /* draw the objects onto scroll1 */
-
- short wgetworldblock (short currentwindow, short posx, short posy);
- /* returns the tile number at a world coordinate */
-
- void wputworldblock (short currentwindow, short posx, short posy,
- short tilenum);
- /* puts a tile at a world coordinate */
-
- void wcopyscroll (short currentwindow, short x, short y);
- /* copies scroll1 onto visual screen */
-
- void wendscroll (short currentwindow);
- /* frees blocks, and shuts down scrolling */
-
- void wfreemap (wgtmap map);
- /* deallocates memory for a map */
-
- short soverlap (short s1, scrollsprite *wobjects1, block *sprites1,
- short s2, scrollsprite *wobjects2, block *sprites2);
- /* sees if two objects overlap */
-
- short windowmode[MAXWINDOWS]; /* Mode for each window (norm or para) */
-
-
-
- wgtmap wloadmap (short currentwindow, char *mapfile, short *tiletypes,
- scrollsprite *wobjects)
- /* Loads a map file into memory */
- {
- wgtmap ptr,orig;
- short ctr, mapver;
- unsigned short size;
-
- if (wgtlibrary == NULL)
- {
- if ((libf = fopen (mapfile, "rb")) == NULL)
- return NULL;
- }
- else
- {
- if ((libf = fopen (wgtlibrary, "rb")) == NULL)
- return NULL;
- readheader ();
- findfile (mapfile);
- if (lresult == 1)
- fseek (libf, lfpos, SEEK_SET);
- if (checkpassword (password) == 0)
- {
- wsetmode (3);
- printf ("Incorrect password");
- exit (1);
- }
- }
-
- if ((wgtlibrary != NULL) & (lresult == 0)) goto mapstop;
-
- fread (&mapver, 2, 1, libf);
- if (mapver != 8975)
- /* not a map file */
- {
- wsetmode (3);
- printf ("Invalid map header: %i\n", mapver);
- if ((mapver > 8971) && (mapver < 8975))
- {
- printf ("This is an earlier WGT map file (not 5.0). Please use the Map Maker to\n");
- printf ("convert it to 5.0 format.\n");
- }
- exit (1);
- }
- fread (&mapwidth[currentwindow], 2, 1, libf);
- fread (&mapheight[currentwindow], 2, 1, libf);
-
- size = mapheight[currentwindow]*mapwidth[currentwindow] * 2;
- ptr = (wgtmap)malloc (size); /* allocate memory */
-
- if (ptr == NULL) return NULL; /* out of memory? */
- orig = ptr; /* original ptr stored */
- if (fread (ptr, size, 1, libf) < 1) /* read in the data */
- {
- wsetmode (3);
- printf ("Read Failed (MAP).\n");
- exit (1);
- }
-
- fread (tiletypes, 256, 2, libf); /* load tile types */
- fread (&ctr, 2, 1, libf); /* number of objects stored in file */
- fread (&wobjects[0], 7, ctr, libf); /* read ctr object structures */
-
- worldmaxx[currentwindow] = mapwidth[currentwindow] * tilewidth[currentwindow]
- - (windowwidth[currentwindow] * tilewidth[currentwindow]) + 1;
-
- worldmaxy[currentwindow] = mapheight[currentwindow] * tileheight[currentwindow]
- - (windowheight[currentwindow] * tileheight[currentwindow]) + 1;
- /* Set maximum scrolling values, ie worldx cannot go past worldmaxx */
- scrollmaps[currentwindow]=orig;
- mapstop:
- ;
- fclose (libf);
- return orig;
- }
-
-
- void wsavemap (short currentwindow, char *filename, wgtmap savemap,
- short *tiletypes, scrollsprite *wobjects, short numobj)
- /* Saves a map file using current object positions
- Useful for saving games in the middle of playing a map
- so you don't have to save games at the start of a level only */
- {
- FILE *fp;
- unsigned short size;
-
- fp = fopen (filename, "wb"); /* open the file */
- size = 8975;
- fwrite (&size, 2, 1, fp); /* write the magic number */
- fwrite (&mapwidth[currentwindow], 2, 1, fp);/* write dimensions */
- fwrite (&mapheight[currentwindow], 2, 1, fp);
-
- size = mapheight[currentwindow] * mapwidth[currentwindow] * 2; /* find size */
- fwrite (savemap, size, 1, fp); /* write size bytes of data from map ptr */
- fwrite (tiletypes, 256, 2, fp);
- size = numobj+1;
- fwrite (&size, 2, 1, fp);
- if (numobj > 0)
- fwrite (&wobjects[0], 7*numobj, 1, fp); /* write object structures */
- fclose (fp);
- }
-
-
- short soverlap (short s1, scrollsprite *wobjects1, block *sprites1,
- short s2, scrollsprite *wobjects2, block *sprites2)
- /* Sees if two objects overlap, by comparing the rectangles each are
- contained in. Pixel precise detection is NOT possible with WGT
- routines. */
- {
- short n1,n2;
- short sw1,sh1,sw2,sh2; /* width/height of both sprites */
- scrollsprite *obj1;
- scrollsprite *obj2;
- block image;
-
- obj1=&wobjects1[s1];
- obj2=&wobjects2[s2];
-
-
- if ((obj1->on & obj2->on)) /* Are they both on? */
- {
- n1 = obj1->num; /* for easier reading */
- n2 = obj2->num;
-
- image = sprites1[n1];
- sw1= *(short *)image; /* Width is first 2 bytes of data */
- image+=2;
- sh1= *(short *)image; /* Height is next 2 bytes of data */
-
- image=sprites2[n2];
- sw2= *(short *)image;
- image+=2;
- sh2= *(short *)image;
-
- if (( obj2->x >= obj1->x - sw2 ) &&
- ( obj2->x <= obj1->x + sw1 ) && /* check all four corners */
- ( obj2->y >= obj1->y - sh2 ) &&
- ( obj2->y <= obj1->y + sh1 )) return 1;
- }
- return 0; /* not colliding */
- }
-
-
- void wscrollwindow (short currentwindow, short wspeedx, short wspeedy)
- {
- short ox1, oy1, ox2, oy2;
- short mode;
- block oldscreen;
- short x, y;
- short x2, y2;
- short a, b;
- short sx, sy;
- short startx;
- short tile;
- short trans;
- short addwidth;
- wgtmap tempmap;
- block *tiles;
-
- tiles = scrolltiles[currentwindow];
-
- oldscreen = abuf;
- ox1 = tx;
- oy1 = ty;
- ox2 = bx;
- oy2 = by;
-
- worldx[currentwindow] += wspeedx;
- worldy[currentwindow] += wspeedy;
-
- if (worldx[currentwindow] < 0)
- worldx[currentwindow] = 0;
-
- if (worldy[currentwindow] < 0)
- worldy[currentwindow] = 0;
-
- if (worldx[currentwindow] > worldmaxx[currentwindow] -1)
- worldx[currentwindow] = worldmaxx[currentwindow] - 1;
-
- if (worldy[currentwindow] > worldmaxy[currentwindow] - 1)
- worldy[currentwindow] = worldmaxy[currentwindow] - 1;
-
- mode = windowmode[currentwindow];
-
- if (mode == 0)
- trans = -1;
- else
- trans = transparenttile;
-
- wsetscreen ((block)scrollblock[currentwindow]);
- wclip (0, 0, windowmaxx[currentwindow], windowmaxy[currentwindow]);
-
- x = worldx[currentwindow];
- y = worldy[currentwindow];
-
- x2 = x / tilewidth[currentwindow];
- y2 = y / tileheight[currentwindow];
-
- sy = - (y % tileheight[currentwindow]);
- startx = - (x % tilewidth[currentwindow]);
-
- tempmap = (wgtmap)scrollmaps[currentwindow];
- /* Make a ptr to the map */
-
- tempmap += y2 * mapwidth[currentwindow] + x2;
- /* Move to the offset of the tile we want */
-
- x = x2;
- x2 += windowwidth[currentwindow] + 1;
- y = y2;
- y2 += windowheight[currentwindow] + 1;
-
- addwidth = 0;
- if (x2 > mapwidth[currentwindow])
- {
- addwidth = x2 - mapwidth[currentwindow];
- x2 = mapwidth[currentwindow];
- }
- if (y2 > mapheight[currentwindow])
- y2 = mapheight[currentwindow];
- addwidth += mapwidth[currentwindow] - windowwidth[currentwindow] - 1;
- for (b = y; b < y2; b++)
- {
- sx = startx;
- for (a = x; a < x2; a++)
- {
- tile = *tempmap++;
- if ((tiles[tile] != NULL) && (tile != trans))
- wputblock (sx, sy, tiles[tile], mode);
- sx += tilewidth[currentwindow];
- }
- sy += tileheight[currentwindow];
- tempmap += addwidth;
- }
- if (oldscreen != 0xa0000)
- wsetscreen (oldscreen);
- else wsetscreen (NULL);
- tx = ox1;
- ty = oy1;
- bx = ox2;
- by = oy2;
- }
-
-
-
- void set_transparent_tile (short tile)
- {
- transparenttile = tile;
- }
-
-
-
- void wshowwindow (short currentwindow, short posx, short posy)
- /* Starts looking at the scrolling world at posx,posy tiles from the
- top left corner (0,0) is the top corner. */
- {
- worldx[currentwindow] = posx * tilewidth[currentwindow];
- worldy[currentwindow] = posy * tileheight[currentwindow];
-
- //wscrollwindow (currentwindow, 0, 0);
- }
-
-
-
- void winitscroll (short currentwindow, short mode, short link, short xwidth,
- short ywidth, block *tileref)
- {
- short tw,th;
- block tileptr;
-
- scrolltiles[currentwindow] = tileref;
- windowmode[currentwindow] = mode;
-
- tw = -1;
- do {
- tw++;
- } while ((tileref[tw] == NULL) & (tw < 256));
-
- tileptr = tileref[tw];
- tw = *(short *)tileptr;
- tileptr += 2;
- th = *(short *)tileptr;
-
- tilewidth[currentwindow] = tw;
- tileheight[currentwindow] = th;
-
- //if ((xwidth > WGT_SYS.xres/tw) || (ywidth > WGT_SYS.yres/th) || (xwidth < 2) || (ywidth < 2))
- /* Invalid window size */
- //{
- //wsetmode (3);
- //printf ("\nInvalid scroll window in call to winitscroll!");
- //exit (1);
- //}
-
- windowminx[currentwindow] = 0;
- windowminy[currentwindow] = 0;
- windowmaxx[currentwindow] = xwidth * tilewidth[currentwindow] - 1;
- windowmaxy[currentwindow] = ywidth * tileheight[currentwindow] - 1;
- /* coords of scrolling area */
-
- if (mode == PARALLAX)
- scrollblock[currentwindow] = scrollblock[link];
- else
- scrollblock[currentwindow] = (wgtmap)wallocblock (
- windowmaxx[currentwindow]+1, windowmaxy[currentwindow]+1);
-
- windowwidth[currentwindow] = xwidth;
- windowheight[currentwindow] = ywidth;
- /* Set up window widths and heights */
- }
-
-
-
- short wgetworldblock (short currentwindow, short posx, short posy)
- /* Returns a tile from the location on a map */
- {
- wgtmap tempmap;
-
- posx = posx / tilewidth[currentwindow];
- posy = posy / tileheight[currentwindow];
- /* Divide by tile size to convert world coords to map coords */
-
- if ((posx < mapwidth[currentwindow]) && (posy < mapheight[currentwindow]) && (posx >= 0) && (posy >= 0))
- {
- tempmap = (wgtmap)scrollmaps[currentwindow];
- /* Make a ptr to the map */
-
- tempmap += posy * mapwidth[currentwindow] + posx;
- /* Move to the offset of the tile we want */
-
- return (*tempmap); /* Return the character at that position */
- }
- else return (-1);
- }
-
-
-
- void wputworldblock (short currentwindow, short posx2, short posy2,
- short tilenum)
- /* Puts a tile onto the map at the given world coordinates. */
- {
- wgtmap tempmap;
-
- posx2 = posx2 / tilewidth[currentwindow];
- posy2 = posy2 / tileheight[currentwindow];
- /* Convert world coords to map coords by dividing by tile size */
-
- if ((posx2 >= 0) && (posx2 < mapwidth[currentwindow]) && (posy2 >= 0) && (posy2 < mapheight[currentwindow]))
- {
- tempmap = scrollmaps[currentwindow];
- tempmap += posy2 * mapwidth[currentwindow] + posx2;
- *tempmap = tilenum;
- /* Put a character to the map */
- }
- }
-
-
-
- void wshowobjects (short currentwindow, short start, short end,
- block *sprites, scrollsprite *wobjects)
- /* Display the objects on top of the assembled data screen */
- {
- block spriteptr;
- short sw,sh;
- short i;
- short ox1, oy1, ox2, oy2;
- block oldscreen;
-
- ox1 = tx;
- oy1 = ty;
- ox2 = bx;
- oy2 = by;
- oldscreen = abuf;
-
- wsetscreen ((block)scrollblock[currentwindow]);
- wclip (0, 0, windowmaxx[currentwindow], windowmaxy[currentwindow]);
-
- /* Go through sprites, from start to end, and draw them */
- for (i = start; i <= end; i++)
- {
- spriteptr = sprites[wobjects[i].num];
-
- if ((wobjects[i].on) && (spriteptr != NULL))
- /* Make sure the object is on, and the block isn't null */
- {
- sw = *(short *)spriteptr;
- spriteptr += 2;
- sh = *(short *)spriteptr;
- spriteptr -= 2;
-
- if ((wobjects[i].x < worldx[currentwindow] + windowmaxx[currentwindow]) &&
- (wobjects[i].y < worldy[currentwindow] + windowmaxy[currentwindow]) &&
- (wobjects[i].x + sw > worldx[currentwindow]) &&
- (wobjects[i].y + sh > worldy[currentwindow]))
- /* Check to see if the object is on the screen */
-
- wputblock (wobjects[i].x - worldx[currentwindow], wobjects[i].y - worldy[currentwindow], spriteptr, 1);
- /* Put the block onto the scroll1 block */
- }
- }
- if (oldscreen != 0xa0000)
- wsetscreen (oldscreen);
- else wsetscreen (NULL);
- tx = ox1;
- ty = oy1;
- bx = ox2;
- by = oy2;
- }
-
-
-
- void wfreemap (wgtmap ptr)
- /* Frees memory from a map file */
- {
- free (ptr);
- }
-
-
-
- void wendscroll (short currentwindow)
- /* Closes up scrolling, and frees virtual screens */
- {
- if (scrollblock[currentwindow] != NULL)
- wfreeblock ((block)scrollblock[currentwindow]);
-
- scrollblock[currentwindow] = NULL;
-
- wsetscreen (NULL);
- }
-
-
-
- unsigned char wgetworldpixel(short currentwindow, short x, short y)
- /* Returns the pixel colour at the specified offset within a tile,
- given the world coordinates in pixels. */
- {
- block emsbl;
- block *blockref;
- short tile; /* Tile number to check */
- short xcoord,ycoord; /* Offset into tile (0-15) */
-
- blockref = scrolltiles[currentwindow];
-
- tile = wgetworldblock(currentwindow, x, y);
-
- emsbl = blockref[tile];
- /* Set a ptr to the block */
-
- xcoord = x % tilewidth[currentwindow]; /* Get x and y offset into tile */
- ycoord = y % tileheight[currentwindow];
-
- emsbl += ycoord * tilewidth[currentwindow] + xcoord + 4;
- /* Move to the correct offset, plus 4 to
- skip over the width and height bytes stored in the block.
- Now we've located the correct tile, and moved to the correct pixel precise
- offset within that tile. */
-
- return *emsbl;
- }
-
-
-
- short is_in_window(short currentwindow, short x, short y, short range)
- /* Returns 1 if coordinate is on screen */
- /* Give a 50 pixel extra range for realism */
- {
- if ((x < worldx[currentwindow] + windowmaxx[currentwindow] + range) &
- (y < worldy[currentwindow] + windowmaxy[currentwindow] + range) &
- (x > worldx[currentwindow] - range) & (y > worldy[currentwindow] - range))
- return 1;
- else return 0;
- }
-
-
-
- short wscreen_coordx(short currentwindow, short xcoord)
- {
- return (xcoord - worldx[currentwindow]);
- }
-
-
-
- short wscreen_coordy(short currentwindow, short ycoord)
- {
- return (ycoord - worldy[currentwindow]);
- }
-
-
-
- void wcopymap (short source, short dest)
- {
- mapwidth[dest] = mapwidth[source];
- mapheight[dest] = mapheight[source];
- scrollmaps[dest] = scrollmaps[source];
-
- worldmaxx[dest] = mapwidth[dest] * tilewidth[dest]
- - (windowwidth[dest] * tilewidth[dest]) + 1;
- worldmaxy[dest] = mapheight[dest] * tileheight[dest]
- - (windowheight[dest] * tileheight[dest]) + 1;
- }
-